home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / ASTOperand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  11.4 KB  |  402 lines  |  [TEXT/KAHL]

  1. /* ASTOperand.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "ASTOperand.h"
  31. #include "TrashTracker.h"
  32. #include "Memory.h"
  33. #include "SymbolTableEntry.h"
  34.  
  35.  
  36. struct ASTOperandRec
  37.     {
  38.         ASTOperandType        Type;
  39.         long                            LineNumberOfSource;
  40.         union
  41.             {
  42.                 long                            IntegerValue;
  43.                 MyBoolean                    BooleanValue;
  44.                 float                            SingleValue;
  45.                 double                        DoubleValue;
  46.                 largefixedsigned    FixedValue;
  47. #if 0
  48.                 char*                            StringValue;
  49. #endif
  50.                 SymbolRec*                SymbolTableEntry;
  51.             } u;
  52.     };
  53.  
  54.  
  55. /* create a new integer literal */
  56. ASTOperandRec*        NewIntegerLiteral(struct TrashTrackRec* TrashTracker,
  57.                                         long IntegerLiteralValue, long LineNumber)
  58.     {
  59.         ASTOperandRec*    IntegerLit;
  60.  
  61.         CheckPtrExistence(TrashTracker);
  62.         IntegerLit = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  63.         if (IntegerLit == NIL)
  64.             {
  65.                 return NIL;
  66.             }
  67.         SetTag(IntegerLit,"ASTOperandRec: NewIntegerLiteral");
  68.  
  69.         IntegerLit->Type = eASTOperandIntegerLiteral;
  70.         IntegerLit->LineNumberOfSource = LineNumber;
  71.         IntegerLit->u.IntegerValue = IntegerLiteralValue;
  72.  
  73.         return IntegerLit;
  74.     }
  75.  
  76.  
  77. /* create a new boolean literal */
  78. ASTOperandRec*        NewBooleanLiteral(struct TrashTrackRec* TrashTracker,
  79.                                         MyBoolean BooleanLiteralValue, long LineNumber)
  80.     {
  81.         ASTOperandRec*    BooleanLit;
  82.  
  83.         CheckPtrExistence(TrashTracker);
  84.         BooleanLit = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  85.         if (BooleanLit == NIL)
  86.             {
  87.                 return NIL;
  88.             }
  89.         SetTag(BooleanLit,"ASTOperandRec: NewBooleanLiteral");
  90.  
  91.         BooleanLit->Type = eASTOperandBooleanLiteral;
  92.         BooleanLit->LineNumberOfSource = LineNumber;
  93.         BooleanLit->u.BooleanValue = BooleanLiteralValue;
  94.  
  95.         return BooleanLit;
  96.     }
  97.  
  98.  
  99. /* create a new single precision literal */
  100. ASTOperandRec*        NewSingleLiteral(struct TrashTrackRec* TrashTracker,
  101.                                         float SingleLiteralValue, long LineNumber)
  102.     {
  103.         ASTOperandRec*    SingleLit;
  104.  
  105.         CheckPtrExistence(TrashTracker);
  106.         SingleLit = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  107.         if (SingleLit == NIL)
  108.             {
  109.                 return NIL;
  110.             }
  111.         SetTag(SingleLit,"ASTOperandRec: NewSingleLiteral");
  112.  
  113.         SingleLit->Type = eASTOperandSingleLiteral;
  114.         SingleLit->LineNumberOfSource = LineNumber;
  115.         SingleLit->u.SingleValue = SingleLiteralValue;
  116.  
  117.         return SingleLit;
  118.     }
  119.  
  120.  
  121. /* create a new double precision literal */
  122. ASTOperandRec*        NewDoubleLiteral(struct TrashTrackRec* TrashTracker,
  123.                                         double DoubleLiteralValue, long LineNumber)
  124.     {
  125.         ASTOperandRec*    DoubleLit;
  126.  
  127.         CheckPtrExistence(TrashTracker);
  128.         DoubleLit = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  129.         if (DoubleLit == NIL)
  130.             {
  131.                 return NIL;
  132.             }
  133.         SetTag(DoubleLit,"ASTOperandRec: NewDoubleLiteral");
  134.  
  135.         DoubleLit->Type = eASTOperandDoubleLiteral;
  136.         DoubleLit->LineNumberOfSource = LineNumber;
  137.         DoubleLit->u.DoubleValue = DoubleLiteralValue;
  138.  
  139.         return DoubleLit;
  140.     }
  141.  
  142.  
  143. /* create a new fixed-point literal */
  144. ASTOperandRec*        NewFixedLiteral(struct TrashTrackRec* TrashTracker,
  145.                                         largefixedsigned FixedLiteralValue, long LineNumber)
  146.     {
  147.         ASTOperandRec*    FixedLit;
  148.  
  149.         CheckPtrExistence(TrashTracker);
  150.         FixedLit = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  151.         if (FixedLit == NIL)
  152.             {
  153.                 return NIL;
  154.             }
  155.         SetTag(FixedLit,"ASTOperandRec: NewFixedLiteral");
  156.  
  157.         FixedLit->Type = eASTOperandFixedLiteral;
  158.         FixedLit->LineNumberOfSource = LineNumber;
  159.         FixedLit->u.FixedValue = FixedLiteralValue;
  160.  
  161.         return FixedLit;
  162.     }
  163.  
  164.  
  165. #if 0
  166. /* create a new string literal.  the string should be a valid heap block and is */
  167. /* stored in the structure (i.e. a copy is NOT made) */
  168. ASTOperandRec*        NewStringLiteral(struct TrashTrackRec* TrashTracker,
  169.                                         char* StringLiteralValue, long LineNumber)
  170.     {
  171.         ASTOperandRec*    StringLit;
  172.  
  173.         CheckPtrExistence(TrashTracker);
  174.         CheckPtrExistence(StringLiteralValue);
  175.         StringLit = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  176.         if (StringLit == NIL)
  177.             {
  178.                 return NIL;
  179.             }
  180.         SetTag(StringLit,"ASTOperandRec:  NewStringLiteral");
  181.  
  182.         StringLit->Type = eASTOperandStringLiteral;
  183.         StringLit->LineNumberOfSource = LineNumber;
  184.         StringLit->u.StringValue = StringLiteralValue;
  185.  
  186.         return StringLit;
  187.     }
  188. #endif
  189.  
  190.  
  191. /* create a new symbol reference. */
  192. ASTOperandRec*        NewSymbolReference(struct TrashTrackRec* TrashTracker,
  193.                                         struct SymbolRec* SymbolTableEntry, long LineNumber)
  194.     {
  195.         ASTOperandRec*    VarRef;
  196.  
  197.         CheckPtrExistence(TrashTracker);
  198.         CheckPtrExistence(SymbolTableEntry);
  199.         VarRef = (ASTOperandRec*)AllocTrackedBlock(sizeof(ASTOperandRec),TrashTracker);
  200.         if (VarRef == NIL)
  201.             {
  202.                 return NIL;
  203.             }
  204.         SetTag(VarRef,"ASTOperandRec: NewSymbolReference");
  205.  
  206.         VarRef->Type = eASTOperandSymbol;
  207.         VarRef->LineNumberOfSource = LineNumber;
  208.         VarRef->u.SymbolTableEntry = SymbolTableEntry;
  209.  
  210.         return VarRef;
  211.     }
  212.  
  213.  
  214. /* find out if it is a symbol */
  215. MyBoolean                    IsOperandASymbol(ASTOperandRec* Operand)
  216.     {
  217.         CheckPtrExistence(Operand);
  218.         return (Operand->Type == eASTOperandSymbol);
  219.     }
  220.  
  221.  
  222. /* get a symbol from the operand */
  223. struct SymbolRec*    GetSymbolFromOperand(ASTOperandRec* Operand)
  224.     {
  225.         CheckPtrExistence(Operand);
  226.         ERROR(!IsOperandASymbol(Operand),PRERR(ForceAbort,
  227.             "GetSymbolFromOperand:  not a symbolic operand"));
  228.         return Operand->u.SymbolTableEntry;
  229.     }
  230.  
  231.  
  232. /* type check the operand node.  this returns eCompileNoError if */
  233. /* everything is ok, and the appropriate type in *ResultingDataType. */
  234. CompileErrors            TypeCheckOperand(DataTypes* ResultingDataType,
  235.                                         ASTOperandRec* Operand, long* ErrorLineNumber,
  236.                                         struct TrashTrackRec* TrashTracker)
  237.     {
  238.         CheckPtrExistence(Operand);
  239.         CheckPtrExistence(TrashTracker);
  240.  
  241.         switch (Operand->Type)
  242.             {
  243.                 default:
  244.                     EXECUTE(PRERR(ForceAbort,"TypeCheckOperand:  unknown operand kind"));
  245.                     break;
  246.                 case eASTOperandIntegerLiteral:
  247.                     *ResultingDataType = eInteger;
  248.                     break;
  249.                 case eASTOperandBooleanLiteral:
  250.                     *ResultingDataType = eBoolean;
  251.                     break;
  252.                 case eASTOperandSingleLiteral:
  253.                     *ResultingDataType = eFloat;
  254.                     break;
  255.                 case eASTOperandDoubleLiteral:
  256.                     *ResultingDataType = eDouble;
  257.                     break;
  258.                 case eASTOperandFixedLiteral:
  259.                     *ResultingDataType = eFixed;
  260.                     break;
  261.                 case eASTOperandSymbol:
  262.                     if (eSymbolVariable != WhatIsThisSymbol(Operand->u.SymbolTableEntry))
  263.                         {
  264.                             *ErrorLineNumber = Operand->LineNumberOfSource;
  265.                             return eCompileMustBeAVariableIdentifier;
  266.                         }
  267.                     *ResultingDataType = GetSymbolVariableDataType(Operand->u.SymbolTableEntry);
  268.                     break;
  269.             }
  270.         return eCompileNoError;
  271.     }
  272.  
  273.  
  274. /* find out what kind of operand this is */
  275. ASTOperandType        OperandWhatIsIt(ASTOperandRec* TheOperand)
  276.     {
  277.         CheckPtrExistence(TheOperand);
  278.         return TheOperand->Type;
  279.     }
  280.  
  281.  
  282. /* generate code for an operand. returns True if successful, or False if it fails. */
  283. MyBoolean                    CodeGenOperand(struct PcodeRec* FuncCode,
  284.                                         long* StackDepthParam, ASTOperandRec* Operand)
  285.     {
  286.         long                        StackDepth;
  287.  
  288.         CheckPtrExistence(FuncCode);
  289.         CheckPtrExistence(Operand);
  290.         StackDepth = *StackDepthParam;
  291.  
  292.         switch (Operand->Type)
  293.             {
  294.                 default:
  295.                     EXECUTE(PRERR(ForceAbort,"CodeGenOperand:  unknown operand type"));
  296.                     break;
  297.  
  298.                 case eASTOperandIntegerLiteral:
  299.                     if (!AddPcodeInstruction(FuncCode,epLoadImmediateInteger,NIL))
  300.                         {
  301.                             return False;
  302.                         }
  303.                     if (!AddPcodeOperandInteger(FuncCode,Operand->u.IntegerValue))
  304.                         {
  305.                             return False;
  306.                         }
  307.                     break;
  308.                 case eASTOperandBooleanLiteral:
  309.                     if (!AddPcodeInstruction(FuncCode,epLoadImmediateInteger,NIL))
  310.                         {
  311.                             return False;
  312.                         }
  313.                     if (!AddPcodeOperandInteger(FuncCode,Operand->u.BooleanValue))
  314.                         {
  315.                             return False;
  316.                         }
  317.                     break;
  318.                 case eASTOperandSingleLiteral:
  319.                     if (!AddPcodeInstruction(FuncCode,epLoadImmediateFloat,NIL))
  320.                         {
  321.                             return False;
  322.                         }
  323.                     if (!AddPcodeOperandFloat(FuncCode,Operand->u.SingleValue))
  324.                         {
  325.                             return False;
  326.                         }
  327.                     break;
  328.                 case eASTOperandDoubleLiteral:
  329.                     if (!AddPcodeInstruction(FuncCode,epLoadImmediateDouble,NIL))
  330.                         {
  331.                             return False;
  332.                         }
  333.                     if (!AddPcodeOperandDouble(FuncCode,Operand->u.DoubleValue))
  334.                         {
  335.                             return False;
  336.                         }
  337.                     break;
  338.                 case eASTOperandFixedLiteral:
  339.                     if (!AddPcodeInstruction(FuncCode,epLoadImmediateInteger,NIL))
  340.                         {
  341.                             return False;
  342.                         }
  343.                     if (!AddPcodeOperandInteger(FuncCode,Operand->u.FixedValue))
  344.                         {
  345.                             return False;
  346.                         }
  347.                     break;
  348.  
  349.                 /* this had better be a variable */
  350.                 case eASTOperandSymbol:
  351.                     switch (GetSymbolVariableDataType(Operand->u.SymbolTableEntry))
  352.                         {
  353.                             default:
  354.                                 EXECUTE(PRERR(ForceAbort,"CodeGenOperand:  bad variable type"));
  355.                                 break;
  356.                             case eBoolean:
  357.                             case eInteger:
  358.                             case eFixed:
  359.                                 if (!AddPcodeInstruction(FuncCode,epLoadIntegerFromStack,NIL))
  360.                                     {
  361.                                         return False;
  362.                                     }
  363.                                 break;
  364.                             case eFloat:
  365.                                 if (!AddPcodeInstruction(FuncCode,epLoadFloatFromStack,NIL))
  366.                                     {
  367.                                         return False;
  368.                                     }
  369.                                 break;
  370.                             case eDouble:
  371.                                 if (!AddPcodeInstruction(FuncCode,epLoadDoubleFromStack,NIL))
  372.                                     {
  373.                                         return False;
  374.                                     }
  375.                                 break;
  376.                             case eArrayOfBoolean:
  377.                             case eArrayOfInteger:
  378.                             case eArrayOfFloat:
  379.                             case eArrayOfDouble:
  380.                             case eArrayOfFixed:
  381.                                 if (!AddPcodeInstruction(FuncCode,epLoadArrayFromStack,NIL))
  382.                                     {
  383.                                         return False;
  384.                                     }
  385.                                 break;
  386.                         }
  387.                     /* stack offsets are negative */
  388.                     if (!AddPcodeOperandInteger(FuncCode,GetSymbolVariableStackLocation(
  389.                         Operand->u.SymbolTableEntry) - StackDepth))
  390.                         {
  391.                             return False;
  392.                         }
  393.                     break;
  394.             }
  395.         StackDepth += 1;
  396.         ERROR(StackDepth != *StackDepthParam + 1,PRERR(ForceAbort,
  397.             "CodeGenOperand:  stack depth error after pushing operand"));
  398.  
  399.         *StackDepthParam = StackDepth;
  400.         return True;
  401.     }
  402.